void init :: init_other()
{
    sph = Sphere();
    sph.setRadius(8);
    rsq = new DefaultRaySceneQuery(scmgr);
    sphq = scmgr->createSphereQuery(sph, qf_movable);
    rsq->setQueryMask(qf_movable);
    current_rayed = scmgr->getEntity("bonome");

    sphq->setSphere(sph);
}
void init :: init()
{
    LOGMSG("-----------------------------------------------------------------");
    LOGMSG("                     INITIALIZING OGRE3D;                        ");
    LOGMSG("-----------------------------------------------------------------");
    LOGMSG("-------- loading resources.cfg --------");
    init_resources();
#ifdef USE_BULLET
    LOGMSG("------- allocating bullet objects -------");
    broadphase      = new btDbvtBroadphase();
    collisionConfig = new btDefaultCollisionConfiguration();
    dispatcher      = new btCollisionDispatcher(collisionConfig);
    //solver        = new btSequentialImpulseConstraintSolver;
    //dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,broadphase,solver,collisionConfiguration);
    colw            = new btCollisionWorld(dispatcher,broadphase,collisionConfig);
    mesh2shape      = new BtOgre :: StaticMeshToShapeConverter;
#endif
    LOGMSG("---------------- allocating GUI  ----------------");
    mGorilla        = new Gorilla   :: Silverback();
#ifdef LASERCAST
    lasercast       = new LaserCast;
#endif
    // warning: some object's initialization depends on other, so *keep* this order
    // this is only required for core object, like camera node and character colobj
    // this is also required to populate objects before placing their colobj
    LOGMSG("--------------- creating the scene ---------------");
    if (GetString("loadlevel")       == "yes") loadlevel("level");
    if (GetString("Populate")        == "yes") Populate();
    if (GetString("enable_loadlist") == "yes") loadlist();
    AddLight("light3");
    AddLight("light3b");
    AddPlane();
    LoadEntity("bonome");
    LOGMSG("-------- creating camera scenenode tree and set camera mode --------");
    n_master = n_root   -> createChildSceneNode("master");
    n_target = n_master -> createChildSceneNode("target");
    n_cam    = n_target -> createChildSceneNode("cam");
    n_recoil = scmgr    -> createSceneNode("recoil");
    setCameraMode(1);
    LOGMSG("---------------- initializing physics ----------------");
#ifdef USE_BULLET
    sphere = new btSphereShape(GetFloat("sphere_radius"));
#endif
    //Nodes.push_back(scmgr->getSceneNode("target"));
    size_t sz = Nodes.size();
    make_scene_query();
#ifdef USE_BULLET
    for(size_t i = 0; i < sz; ++ i)
        add_col_obj(i);
#endif
    init_bullets();

#ifndef LASERCAST
    init_laser();
#endif
    LOGMSG("--------------- initializing inputs and GUI ---------------");
    init_inputs();
    init_gorilla();
    
    mat //= scmgr->getEntity("bonome")->getMaterial();
        = scmgr->getEntity("bonome")->getSubEntity(0)->getMaterial();
    colorval1 = ColourValue(0.2f,0.f,0.f);
    colorval2 = ColourValue(0.f,0.f,0.2f);

    //material_hover = create_hover_material
    //  (scmgr->getEntity("bonome")->getSubEntity(0)->getMaterial());

    LOGMSG("---------------- reading parameters from config-file ----------------"); 
    translate           = Vec3 (0.0f,0.0f,0.0f);
    translate2          = Vec3 (0.0f,0.0f,0.0f);
    rotating_speed      = GetFloat ("rotating_speed");
    moving_speed        = GetFloat ("moving_speed");
    stop                = false;
    offset              = GetVect3("offset");

    LOGMSG("---------------- misc ogre parameters ----------------"); 
//  window -> reposition(20, 20);
    viewport -> setBackgroundColour(ColourValue(0.1f, 0.1f, 0.1f));
    LOGMSG("---------------- simple crosshair ----------------"); 
    if(GetInt("crosshair") == 1)
        OverlayManager :: getSingletonPtr() -> getByName("jokoon/crosshair") -> show();

    init_procedural();
    LOGMSG("---------------- game mechanics ----------------");
    machine         = new game_machine(timeSinceLastFrame);
    //machine->init();

    init_other();

//  LOGMSG("colobj: "+TO_STR(colw->getCollisionObjectArray().size()));
//  LOGMSG("Nodes: "+TO_STR(Nodes.size()));
//  LOGMSG("Entities: "+TO_STR(Entities.size()));
//  LOGMSG("sizeof app class: "+TO_STR(sizeof(init)));

    LOGMSG("-----------------------------------------------------------------");
    LOGMSG("        FINISHED INITIALIZING OGRE3D; begginning gameloop        ");
    LOGMSG("-----------------------------------------------------------------");
}
void init :: make_scene_query()
{
    //sc_qry = static_cast<DefaultSphereSceneQuery *> (scmgr->createSphereQuery(ogre_sphere, 0));
}
/*void init :: add_debug_gizmo(string name)
{
    // laser DOT
    //BillboardSet * white_dot[16];
    //Billboard * gizmo[16];
    {
        float laserdot_scale = GetFloat("dotscale");
        n_root -> createChildSceneNode(name)
            -> attachObject (scmgr -> createBillboardSet(name));

        scmgr->getSceneNode(name) -> setScale(Vec3(laserdot_scale,laserdot_scale,laserdot_scale));
        scmgr->getBillboardSet(name)-> createBillboard(Ogre :: Vector3(0, 0, 0));

        switch(diagnose_vect.size()%3)
        {
        case 0: scmgr->getBillboardSet(name) -> setMaterialName("jokoon/gizmo"); break;
        case 1: scmgr->getBillboardSet(name) -> setMaterialName("jokoon/gizmo2"); break;
        case 2: scmgr->getBillboardSet(name) -> setMaterialName("jokoon/gizmo3"); break;
        default: break;
        }

    //n_laserdot     = n_root -> createChildSceneNode("laser dot");
    //bb_laserdot    = scmgr  -> createBillboardSet("laser dot");
    //n_laserdot -> attachObject (bb_laserdot);
    //bb_laserdot -> setMaterialName("jokoon/laser_dot");
    //float laserdot_scale = GetFloat("dotscale");
    //n_laserdot -> setScale(Vec3(laserdot_scale,laserdot_scale,laserdot_scale));
    //bboard         = bb_laserdot -> createBillboard(Ogre :: Vector3(0, 0, 0));


    }
}*/
string          init :: GetString(string _s)
{
    return configfile->getSetting(_s);
}
float           init :: GetFloat    (string _s)
{
    float result = float(0xdeadbeef);
    istringstream istrstr(configfile -> getSetting(_s, StringUtil :: BLANK, "1.0"));
    istrstr >> result;
    return result;
}
int             init :: GetInt  (string _s)
{
    int result = 0xdeadbeef;
    istringstream istrstr(configfile -> getSetting(_s, StringUtil :: BLANK, "0"));
    istrstr >> result;
    return result;
}
Vec3            init :: GetVect3    (string _s)
{
    istringstream iss(configfile -> getSetting(_s));
    // string s = configfile -> getSetting(_s);
    float x, y, z;

    iss >>  x >> y >> z;

    return Vec3(x, y, z);
}
Ogre::Vector2   init    :: GetVect2 (string _s)
{
    istringstream iss(configfile -> getSetting(_s));
    // string s = configfile -> getSetting(_s);
    float x, y;

    iss >> x >> y;

    return Ogre::Vector2(x, y);
}
#ifdef USE_YAML
string init :: get_scalar(const ynode & node)
{
    string s;
    switch(node.Type())
    {
    case YAML::NodeType::Scalar:
        node >> s;
        return s;
    case YAML::NodeType::Null:
        return string("void");
    default: 
        assert(0 && "error, neither null or scalar !");
    }
}
#endif
void init :: set_mask8(char & mask, char value, bool set)
{
    if(set)
        mask |= value;
    else
        mask &= ~ (0 | value); // unsets
}
void init :: set_mask16(short & mask, short value, bool set)
{
    if(set)
        mask |= value;
    else
        mask &= ~ (0 | value); // unsets
}
string init :: tabulate(string s, size_t z)
{
    string a;
    for(size_t i = 0; i < z - s.size(); ++ i)
        a.append(" ");
    return s+a;
}
string init :: inspect_mask(char c)
{
    string s;
    if(c & CONIC) s += "cone ";
    if(c & BELL) s += "bell ";
    if(c & CHAIN) s += "chain ";
    if(c & MISSILE) s += "missile ";
    return s;   
}
SceneTypeMask   init :: GetScMgrType()
{
    string str = configfile -> getSetting("SceneManager");
    if(str == "BSP_INTERIOR") return ST_INTERIOR;
    if(str == "OCTREE_GENERIC") return ST_GENERIC;
    if(str == "PAGING") return ST_EXTERIOR_REAL_FAR;
    return ST_GENERIC;
}

    void            init :: Populate()
{
    // REMINDER: FOR THE 5432nd TIME, HEIGHT IS Y (forward is x)
    int population = GetInt("population");
    istringstream iss(configfile -> getSetting("pop_zone"));
    float  A_x, A_z, B_x, B_z;
    iss >> A_x >> A_z >> B_x >> B_z;

    std::string pop_mesh = configfile -> getSetting("pop_mesh");
    float
        range_xz_down   = GetFloat("range_xz_down"),
        range_xz_up     = GetFloat("range_xz_up");

    for(int i = 0 ; i < population; ++ i)
    {
        velocities.push_back(Vec3(Math::RangeRandom(range_xz_down, range_xz_up),0,
            Math::RangeRandom(range_xz_down, range_xz_up)));
        SceneNode * node = n_root -> createChildSceneNode("monster_"+TO_STR(i));
        Entity * ent = scmgr -> createEntity(pop_mesh);
        node -> attachObject(ent);
        
        node -> setPosition(
            Math::RangeRandom(A_x, B_x),
            Real(0),
            Math::RangeRandom(A_z, B_z)
            );
        Nodes.push_back(node);
        Entities.push_back(ent);
    }
}
void            init :: LoadEntity(string _s)
{
    istringstream iss(configfile -> getSetting(_s));
    float x, y, z, scale;
    string mesh_filename, material_name, flag;

    iss >> mesh_filename >> scale >> material_name >> x >> y >> z >> flag;

    /* "-" loads the same named .mesh / material */
    Entity * ent;
    if (mesh_filename == "-")       ent = scmgr -> createEntity(_s, _s + ".mesh");
    else                            ent = scmgr -> createEntity(_s, mesh_filename);

    if (material_name == "-")       ent -> setMaterialName(_s + ".material");
    else if (material_name == "x")  LOGMSG("No material used for "+_s);
    else                            ent -> setMaterialName(material_name);
    
    SceneNode * node;
    if (flag == "target")
    {
        if (configfile -> getSetting("attach_target") == "yes")
        {
            e_target = ent;
            //Nodes.push_back(
        }
        else
            LOGMSG("Not attaching target");
    }
    else
    {
        node = n_root->createChildSceneNode(_s, Vec3(x, y, z));
        node -> attachObject(ent);
        Nodes.push_back(node);
        Entities.push_back(ent);
        ent->setQueryFlags(qf_movable);
        velocities.push_back(Vec3());

        LOGMSG("Creating collision object");
        //add_col_obj(Nodes.size()-1);
    }
    
}
void            init :: AddPlane()
{
    Ogre :: Plane plane(Ogre :: Vector3 :: UNIT_Y, -1); // -1 is the y position

    float plane_width = GetFloat("plane_width");
    float plane_depth = GetFloat("plane_depth");

    Ogre :: MeshManager :: getSingleton().createPlane
        ("plane",
            ResourceGroupManager :: DEFAULT_RESOURCE_GROUP_NAME, plane,
            plane_width, plane_depth, 10, 10, // width height xseg yseg
            true,
            1, 5, 5,
            //Vec3(1,1,4));
            Ogre :: Vector3 :: UNIT_Z);

    entplane = scmgr -> createEntity("LightPlaneEntity", "plane");
    n_root -> createChildSceneNode() -> attachObject(entplane);
    entplane -> setMaterialName("jokoon/grass");
    entplane->setQueryFlags(qf_static);
}
void            init :: loadlist()
{
    Ogre::StringVector strs = StringUtil::split(GetString("loadlist"));
    for(size_t i = 0; i < strs.size(); ++i)
        LoadEntity(strs[i]);
}
void            init :: loadlevel(string level)
{
    e_ground = scmgr->createEntity(GetString(level));
    n_root->createChildSceneNode(level)->attachObject(e_ground);

#ifdef USE_BULLET
    mesh2shape = new BtOgre::StaticMeshToShapeConverter(e_ground);
    btCollisionShape * shape_ground = mesh2shape -> createTrimesh();
    btCollisionObject * colobj_ground = new btCollisionObject;
    colobj_ground -> setCollisionShape(shape_ground);

    col_dgb = new BtOgre::DebugCollisionDrawer(scmgr->getSceneNode(level),colw);

    colw->setDebugDrawer(col_dgb);
    col_dgb->setDebugMode(false);

    delete_it.push_back(col_dgb);
    delete_it.push_back(mesh2shape);
    delete_it.push_back(colobj_ground);
    delete_it.push_back(shape_ground);

    colw -> addCollisionObject(colobj_ground);
#endif
}
SceneNode *     init :: AddLight(string _s)
{
    istringstream iss(configfile -> getSetting(_s));
    // string s = configfile -> getSetting(_s);
    float x, y, z,
        dir_x, dir_y, dir_z,
        color_r, color_g, color_b;
    string type;

    iss >> dir_x >> dir_y >> dir_z
        >> type
        >> x >> y >> z
        >> color_r >> color_g >> color_b;

    SceneNode * node = scmgr -> createSceneNode(_s);
    Light * light = scmgr -> createLight(_s);
    
    if(type == "DIR")
    {
        light -> setType(Light :: LT_DIRECTIONAL);
        light -> setDirection(dir_x, dir_y, dir_z);
    }
    if(type == "SPOT")
    {   
        light -> setType(Light :: LT_SPOTLIGHT);
        light -> setDirection(dir_x, dir_y, dir_z);
    }

    if(type == "POINT") light -> setType(Light :: LT_POINT);
    
    node -> attachObject(light);
    light->setSpecularColour(Real(color_r), Real(color_g), Real(color_b));
    light->setDiffuseColour(Real(color_r), Real(color_g), Real(color_b));
    ((scmgr) -> getRootSceneNode()) -> addChild(node);
    
    node -> setPosition(x, y, z);

    return node;
}
MaterialPtr     init :: create_hover_material(MaterialPtr mat)
{
    MaterialPtr ret;
    ret = mat->clone(mat->getName()+"_hover");
    ret->setAmbient(ColourValue(0.1f,0.1f,0.1f,0.1f));
    ret->setDiffuse(ColourValue(0.1f,0.1f,0.1f,0.1f));
    return ret;
}

void init :: init_procedural()
{
}
/*
memo from wiki:
The argument to createSceneManager (getSceneManager in older releases) specifies the type of scene manager to use, based on the following values:

ST_GENERIC - Generic scene manager (Octree if you load Plugin_OctreeSceneManager, DotScene if you load Plugin_DotSceneManager)
ST_EXTERIOR_CLOSE - Terrain Scene Manager
ST_EXTERIOR_FAR - Nature scene manager <sub>This mode is not present anymore in Ogre 1.0. Use "Terrain", or "Paging Landscape" instead.</sub>
ST_EXTERIOR_REAL_FAR - Paging Scene Manager
ST_INTERIOR - BSP scene manager
*/
